{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 自定义绘制ks曲线的函数\n",
    "def plot_ks(y_test, y_score, positive_flag):\n",
    "    # 对y_test,y_score重新设置索引\n",
    "    y_test.index = np.arange(len(y_test))\n",
    "    #y_score.index = np.arange(len(y_score))\n",
    "    # 构建目标数据集\n",
    "    target_data = pd.DataFrame({'y_test':y_test, 'y_score':y_score})\n",
    "    # 按y_score降序排列\n",
    "    target_data.sort_values(by = 'y_score', ascending = False, inplace = True)\n",
    "    # 自定义分位点\n",
    "    cuts = np.arange(0.1,1,0.1)\n",
    "    # 计算各分位点对应的Score值\n",
    "    index = len(data.y_score)*cuts\n",
    "    scores = data.y_score.iloc[index.astype('int')]\n",
    "    # 根据不同的Score值，计算Sensitivity和Specificity\n",
    "    Sensitivity = []\n",
    "    Specificity = []\n",
    "    for score in scores:\n",
    "        # 正例覆盖样本数量与实际正例样本量\n",
    "        positive_recall = target_data.loc[(target_data.y_test == positive_flag) & (target_data.y_score>score),:].shape[0]\n",
    "        positive = sum(target_data.y_test == positive_flag)\n",
    "        # 负例覆盖样本数量与实际负例样本量\n",
    "        negative_recall = target_data.loc[(target_data.y_test != positive_flag) & (target_data.y_score<=score),:].shape[0]\n",
    "        negative = sum(target_data.y_test != positive_flag)\n",
    "        Sensitivity.append(positive_recall/positive)\n",
    "        Specificity.append(negative_recall/negative)\n",
    "    # 构建绘图数据\n",
    "    plot_data = pd.DataFrame({'cuts':cuts,'y1':1-np.array(Specificity),'y2':np.array(Sensitivity), \n",
    "                              'ks':np.array(Sensitivity)-(1-np.array(Specificity))})\n",
    "    # 寻找Sensitivity和1-Specificity之差的最大值索引\n",
    "    max_ks_index = np.argmax(plot_data.ks)\n",
    "    plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y1.tolist()+[1], label = '1-Specificity')\n",
    "    plt.plot([0]+cuts.tolist()+[1], [0]+plot_data.y2.tolist()+[1], label = 'Sensitivity')\n",
    "    # 添加参考线\n",
    "    plt.vlines(plot_data.cuts[max_ks_index], ymin = plot_data.y1[max_ks_index], \n",
    "               ymax = plot_data.y2[max_ks_index], linestyles = '--')\n",
    "    # 添加文本信息\n",
    "    plt.text(x = plot_data.cuts[max_ks_index]+0.01,\n",
    "             y = plot_data.y1[max_ks_index]+plot_data.ks[max_ks_index]/2,\n",
    "             s = 'KS= %.2f' %plot_data.ks[max_ks_index])\n",
    "    # 显示图例\n",
    "    plt.legend()\n",
    "    # 显示图形\n",
    "    plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 导入虚拟数据\n",
    "virtual_data = pd.read_excel(r'C:\\Users\\Administrator\\Desktop\\virtual_data.xlsx')\n",
    "# 应用自定义函数绘制k-s曲线\n",
    "plot_ks(y_test = virtual_data.Class, y_score = virtual_data.Score,positive_flag = 'P')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 导入第三方模块\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn import linear_model\n",
    "\n",
    "# 读取数据\n",
    "sports = pd.read_csv(r'C:\\Users\\Administrator\\Desktop\\Run or Walk.csv')\n",
    "# 提取出所有自变量名称\n",
    "predictors = sports.columns[4:]\n",
    "# 构建自变量矩阵\n",
    "X = sports.ix[:,predictors]\n",
    "# 提取y变量值\n",
    "y = sports.activity\n",
    "# 将数据集拆分为训练集和测试集\n",
    "X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.25, random_state = 1234)\n",
    "\n",
    "# 利用训练集建模\n",
    "sklearn_logistic = linear_model.LogisticRegression()\n",
    "sklearn_logistic.fit(X_train, y_train)\n",
    "# 返回模型的各个参数\n",
    "print(sklearn_logistic.intercept_, sklearn_logistic.coef_)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 模型预测\n",
    "sklearn_predict = sklearn_logistic.predict(X_test)\n",
    "# 预测结果统计\n",
    "pd.Series(sklearn_predict).value_counts()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# 导入第三方模块\n",
    "from sklearn import metrics\n",
    "# 混淆矩阵\n",
    "cm = metrics.confusion_matrix(y_test, sklearn_predict, labels = [0,1])\n",
    "cm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "Accuracy = metrics.scorer.accuracy_score(y_test, sklearn_predict)\n",
    "Sensitivity = metrics.scorer.recall_score(y_test, sklearn_predict)\n",
    "Specificity = metrics.scorer.recall_score(y_test, sklearn_predict, pos_label=0)\n",
    "print('模型准确率为%.2f%%:' %(Accuracy*100))\n",
    "print('正例覆盖率为%.2f%%' %(Sensitivity*100))\n",
    "print('负例覆盖率为%.2f%%' %(Specificity*100))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 混淆矩阵的可视化\n",
    "# 导入第三方模块\n",
    "import seaborn as sns\n",
    "import matplotlib.pyplot as plt\n",
    "# 绘制热力图\n",
    "sns.heatmap(cm, annot = True, fmt = '.2e',cmap = 'GnBu')\n",
    "# 图形显示\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# y得分为模型预测正例的概率\n",
    "y_score = sklearn_logistic.predict_proba(X_test)[:,1]\n",
    "# 计算不同阈值下，fpr和tpr的组合值，其中fpr表示1-Specificity，tpr表示Sensitivity\n",
    "fpr,tpr,threshold = metrics.roc_curve(y_test, y_score)\n",
    "# 计算AUC的值\n",
    "roc_auc = metrics.auc(fpr,tpr)\n",
    "\n",
    "# 绘制面积图\n",
    "plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')\n",
    "# 添加边际线\n",
    "plt.plot(fpr, tpr, color='black', lw = 1)\n",
    "# 添加对角线\n",
    "plt.plot([0,1],[0,1], color = 'red', linestyle = '--')\n",
    "# 添加文本信息\n",
    "plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)\n",
    "# 添加x轴与y轴标签\n",
    "plt.xlabel('1-Specificity')\n",
    "plt.ylabel('Sensitivity')\n",
    "# 显示图形\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 调用自定义函数，绘制K-S曲线\n",
    "plot_ks(y_test = y_test, y_score = y_score, positive_flag = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# -----------------------第一步 建模 ----------------------- #\n",
    "# 导入第三方模块\n",
    "import statsmodels.api as sm\n",
    "# 将数据集拆分为训练集和测试集\n",
    "X_train, X_test, y_train, y_test = model_selection.train_test_split(X, y, test_size = 0.25, random_state = 1234)\n",
    "# 为训练集和测试集的X矩阵添加常数列1\n",
    "X_train2 = sm.add_constant(X_train)\n",
    "X_test2 = sm.add_constant(X_test)\n",
    "# 拟合Logistic模型\n",
    "sm_logistic = sm.formula.Logit(y_train, X_train2).fit()\n",
    "# 返回模型的参数\n",
    "sm_logistic.params"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# -----------------------第二步 预测构建混淆矩阵 ----------------------- #\n",
    "# 模型在测试集上的预测\n",
    "sm_y_probability = sm_logistic.predict(X_test2)\n",
    "# 根据概率值，将观测进行分类，以0.5作为阈值\n",
    "sm_pred_y = np.where(sm_y_probability >= 0.5, 1, 0)\n",
    "# 混淆矩阵\n",
    "cm = metrics.confusion_matrix(y_test, sm_pred_y, labels = [0,1])\n",
    "cm"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# -----------------------第三步 绘制ROC曲线 ----------------------- #\n",
    "# 计算真正率和假正率 \n",
    "fpr,tpr,threshold = metrics.roc_curve(y_test, sm_y_probability)\n",
    "# 计算auc的值  \n",
    "roc_auc = metrics.auc(fpr,tpr)\n",
    "# 绘制面积图\n",
    "plt.stackplot(fpr, tpr, color='steelblue', alpha = 0.5, edgecolor = 'black')\n",
    "# 添加边际线\n",
    "plt.plot(fpr, tpr, color='black', lw = 1)\n",
    "# 添加对角线\n",
    "plt.plot([0,1],[0,1], color = 'red', linestyle = '--')\n",
    "# 添加文本信息\n",
    "plt.text(0.5,0.3,'ROC curve (area = %0.2f)' % roc_auc)\n",
    "# 添加x轴与y轴标签\n",
    "plt.xlabel('1-Specificity')\n",
    "plt.ylabel('Sensitivity')\n",
    "# 显示图形\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# -----------------------第四步 绘制K-S曲线 ----------------------- #\n",
    "# 调用自定义函数，绘制K-S曲线\n",
    "sm_y_probability.index = np.arange(len(sm_y_probability))\n",
    "plot_ks(y_test = y_test, y_score = sm_y_probability, positive_flag = 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import pandas as pd"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [Root]",
   "language": "python",
   "name": "Python [Root]"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
